package com.whately.core.base.config;

import cn.hutool.core.util.ClassUtil;
import com.whately.core.base.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import java.lang.reflect.Field;
import java.util.Arrays;

/**
 * 执行时机为容器启动完成的时候
 * 检查 service 不能调用 service
 */
@Component
@Slf4j
@Profile({"dev", "local"}) //只本地和测试环境开启
public class WhatelyCheckCodingRulesUtil implements ApplicationRunner {

    private final String packageStyle="com.whately.*.service.*";
    private final String packageStyleOther="com.whately.service.*";
    @Override
    public void run(ApplicationArguments args) {
        log.info("WhatelyCheckCodingRulesUtil enter");
        String[] beans = SpringConfigurer.getApplicationContext().getBeanDefinitionNames();
        Arrays.sort(beans);
        PathMatcher matcher = new AntPathMatcher();
        for (String beanName : beans)
        {

            Class<?> beanType = SpringConfigurer.getApplicationContext().getType(beanName);

            String packageName = beanType.getPackage().getName();
            packageName = packageName +".";
            boolean pass = matcher.match(packageStyle, packageName)||matcher.match(packageStyleOther, packageName);
            if(pass){
                //
                String clsName = beanType.getName();
                if(clsName.indexOf("$$")>0){
                    clsName = clsName.substring(0,clsName.indexOf("$$"));
                }

                try{
                    Class ins = Class.forName(clsName);
                    Field[] fields = ins.getDeclaredFields();
                    for (Field field : fields) {
                        field.setAccessible(true);
                        Class<?> attrFieldType = field.getType();
                        boolean isBasic = ClassUtil.isBasicType(attrFieldType);
                        if(!isBasic){

                            String fieldPackage = attrFieldType.getPackage().getName();
                            fieldPackage = fieldPackage +".";
                            if(matcher.match(packageStyle, fieldPackage)||matcher.match(packageStyleOther, fieldPackage)){
                                throw new ServiceException(400,"code format error service invoke service : clsName "+clsName+" , field "+fieldPackage+attrFieldType.getSimpleName());
                            }
                        }


                    }
                }catch (Exception e){
                    log.error("WhatelyCheckCodingRulesUtil error",e);
                    throw new RuntimeException(e);
                }

            }

        }
    }





}
